﻿using Microsoft.VisualBasic;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;

namespace OrderApp
{
    public class Program
    {
        public abstract class  Information
        {
            public abstract bool Equal(Object obj);
            public abstract new void ToString(); 
        }

        public class Custumor:Information 
        {
            public string name { get; set; }
            public int phone_number { get; set; }
            public string home { get; set; }
            public Custumor (string name,int phone_number,string home)
            {
                this.name = name;
                this.phone_number = phone_number;
                this.home = home;
            }
            public Custumor() { }
         
            
            public override bool Equal(Object obj)
            {
                return obj is Custumor custumor&&name==custumor.name &&phone_number==custumor.phone_number&&home==custumor .home ;
                
            }
            public override void ToString()
            {
                Console.WriteLine("The name of the custumor is " + name);
                Console.WriteLine("The phone number of the custumor is " + phone_number);
                Console.WriteLine("The home of the custumor is " + home);
            }
        }
        public class Product:Information 
        {
            public string name { get; set; }
            public decimal unitprice { get; set; }
            public int quantity { get; set; }
            public decimal Amount { get; set; }
            public Product(string name,decimal unitprice,int quantity)
            {
                this.name = name;
                this.unitprice = unitprice;
                this.quantity = quantity;
                this.Amount = unitprice * quantity;
            }
            public Product(){  }
            public override bool Equal(object obj)
            {
                return obj is Product product&&name==product .name &&unitprice ==product .unitprice &&quantity ==product .quantity ;
            }
            public override void ToString()
            {
                Console.WriteLine("The " + name + " is per " + unitprice+"$");
                Console.WriteLine("The quantity of the product is " + quantity);
                Console.WriteLine(Amount);
            }
        }
        public class Order:Information 
        {
            public int OrderId { get; set; }
            public Custumor custumor { get; set; }
            public List<OrderDetail> OrderDetails = new List<OrderDetail>();
            public decimal TotalAmount 
            { 
                get
                {
                    decimal total = 0;
                    foreach(OrderDetail orderdetail in OrderDetails)
                    {
                        total += orderdetail.product.Amount;
                    }
                    return total;
                }
            }

            public Order(Custumor custumor,int orderid)
            {
                this.custumor = custumor;
                this.OrderId = orderid;
            }
            public Order() { }

            public override bool Equal(object obj)
            {
                return obj is Order order&&OrderId==order.OrderId&&custumor==order.custumor &&OrderDetails==order .OrderDetails ;

            }
            public override void ToString()
            {
                Console .WriteLine ("The ID of the Order is "+OrderId );
                custumor.ToString();
                foreach(OrderDetail orderDetail in OrderDetails)
                {
                    orderDetail.ToString();
                }
                Console.WriteLine("The total amount is " + TotalAmount);
            }
            
        }
        public class OrderDetail:Information
        { 
            public Product product { get; set; }
            
            public OrderDetail(Product product)
            {
                this.product = product;
            }
            public OrderDetail() { }
           
            
            public override bool Equal(object obj)
            {
                return obj is OrderDetail detail && detail.product.Equal(obj);
            }
            public override void ToString()
            {
                product.ToString();
            }

        }
        public class OrderServices
        {
            private List<Order> orders = new List<Order>();

            public void AddOrder(Order order)
            {
                bool result=true;
                foreach(Order order1 in orders)
                {
                    if (order.Equal(order1))
                    {
                        result = false;
                    }
                }
                if (result) 
                {
                    orders.Add(order);
                }
                else { Console.WriteLine("The order has been existing"); }
            }

            public void RemoveOrder(int orderId)
            {
                Order ? o = orders.FirstOrDefault(o => o.OrderId == orderId);
                if (o == null)
                {
                    throw new Exception("Order not found");
                }
                else
                {
                    orders.Remove(o);
                }
            }

            public void UpdateOrder(int orderId,Order updateorder)
            {
                var OrderIndex = orders.FindIndex(o => { return o.OrderId == orderId; });
                if(OrderIndex == -1)
                {
                    throw new Exception("The order does not exist.");
                }
                else
                {
                    orders[orderId] = updateorder;
                }
            }

            public void SortByTotalAmount()
            {
                List<Order> neworders = (List<Order>)orders.OrderByDescending(o => o.TotalAmount);
                orders = neworders;
            }

            public void SortByOrderId()
            {
                List<Order> neworders = (List<Order>)orders.OrderByDescending(o => o.OrderId);
                orders = neworders;
            }

            public void SortByCustumorName()
            {
                List<Order> neworders = (List<Order>)orders.OrderByDescending(o => o.custumor .name.First ());
                orders = neworders;
            }

            public void ShowInformationBySort(int i)
            {
                List<Order> neworders = (List<Order>)orders.OrderByDescending(o => o.TotalAmount);
                switch (i)
                {
                    case 1:
                        {
                            foreach(Order no in neworders )
                            {
                                Console.WriteLine(no.OrderId);
                            }
                        }
                        break;
                    case 2:
                        {
                            foreach (Order no in neworders)
                            {
                                no.custumor  .ToString ();
                            }
                        }
                        break;
                    case 3:
                        {
                            foreach(Order no in neworders)
                            {
                                foreach (OrderDetail orderDetail in no.OrderDetails)
                                {
                                    orderDetail.ToString();
                                }
                            }
                        }
                        break;
                    case 4:
                        {
                            foreach (Order no in neworders)
                            {
                                Console.WriteLine(no.TotalAmount);
                            }
                        }
                        break;
                    default:
                        break;
                }
            }

            public void ShowAllOrder()
            {
                foreach(Order order in orders)
                {
                    order.ToString();
                }
            }
        }
        static void Main(string[] args)
        {
            var orderservices = new OrderServices();

            Order order1 = new Order() { custumor = new Custumor() { name = "Sam", home = "BeiJing", phone_number = 1111111 }, OrderId = 1 };
            order1.OrderDetails.Add(new OrderDetail { product = new Product("A", 10, 5) });
            order1.OrderDetails.Add(new OrderDetail { product = new Product("B", 20, 5) });
            orderservices.AddOrder(order1);

            Order order2 = new Order() { custumor = new Custumor() { name = "Bob", home = "HuBei", phone_number = 2222222 }, OrderId = 2 };
            order2.OrderDetails.Add(new OrderDetail { product = new Product("C",9,5) });
            order2.OrderDetails.Add(new OrderDetail { product = new Product("D",15,5)  });
            orderservices.AddOrder(order2);

            orderservices.ShowAllOrder();
        }
    }
}
